package top.wuxiaohan.operatingSystemCourse.kernel;

import top.wuxiaohan.operatingSystemCourse.myRunnable.MyRunnable;

/**
 * 进程控制块
 */
public class PCB {
    /**
     * 进程的ID<br/>
     * 在初始化时分配，进程生命周期内不会改变
     */
    private int pid;
    /**
     * 进程名<br/>
     * 在初始化时分配，进程生命周期内不会改变
     */
    private String pidName;
    /**
     * 资源队列链表，每申请一种资源就在链表头部插入一个资源块<br/>
     * 进程初始化时可以不分配资源
     */
    private RCB resources;
    /**
     * 进程状态，ready or block<br/>
     * 如果建立进程时不分配资源，则默认为ready
     * 如果建立进程失败，设置为error
     * 暂时用不到……
     */
    private Type type;
    /*
     * 进程就绪/阻塞队列<br/>
     * 指向链表的下一个节点<br/>
     * 暂时用不到...
     */
    //private PCB listNode;
    /**
     * 二叉树，两边分别为父进程和子进程的节点<br/>
     * parentPCB指向父进程，childPCB指向子进程（可为空）<br/>
     * 父进程在初始化时设置，进程生命周期内不会改变
     */
    private PCB parentPCB, childPCB;
    /**
     * 进程优先级，目前仅支持三种优先级：<br/>
     * 0:init进程&nbsp;
     * 1:用户进程&nbsp;
     * 2:系统进程&nbsp;
     */
    private int priority;
    /**
     * 运行代码接口，需重载myRunnable接口中的run()方法，类似于Java的Runnable接口
     */
    private MyRunnable myRunnable;

    /**
     * 构造函数
     * @param pid 进程号
     * @param pidName 进程名
     * @param parentPCB 父进程PCB
     * @param priority 进程优先级
     * @param myRunnable 运行代码接口
     */
    public PCB(int pid, String pidName, PCB parentPCB, int priority, MyRunnable myRunnable) {

        this.pid = pid;
        this.pidName = pidName;
        //init进程通常没有父进程，因此内核在建立线程时需要做好判断
        this.parentPCB = parentPCB;
        //如果有父进程，将本PCB插入到父进程的子进程队列中
        if(parentPCB != null) {
            parentPCB.addChildPCB(this);
        }
        this.priority = priority;
        this.myRunnable = myRunnable;
        type = Type.READY;

        //进程状态取决于内核创建进程时将其挂载在何处（ready队列或是block队列）
        //事实上是把进程状态的查询方法交给了内核去实现（毕竟队列管理是内核在做）

        //TODO 想添加这样一种机制：进程建立之后内核查询进程状态，如果是ready或block或run证明进程建立成功，如果是error则表示进程创建失败，是哪里出了问题
    }

    /**
     * 初始化方法<br/>
     * 暂时没有用到诶
     */
    public int initialize() {

        return 0;
    }

    /**
     * 获取PID
     * */
    public int getPID() {
        return pid;
    }

    /**
     * 获取进程名
     * */
    public String getPidName() { return pidName; }

    //TODO 与RCB相关的：资源队列的管理，包括获取链表头、插入链表、获取链表长度、摘掉链表节点、查找资源（通过资源id）等

    /**
     * 获取子进程链表（获取链表头）
     * */
    public PCB getChildPCB() { return childPCB; }

    /**
     * 在进程树上添加一个子进程（插入链表节点，插入链表头部）
     * */
    public void addChildPCB(PCB childPCB) {
        PCB tempPCB = this.childPCB;
        this.childPCB = childPCB;
        childPCB.childPCB = tempPCB;
    }

    /**
     * 获取父进程PCB
     * */
    public PCB getParentPCB() { return parentPCB; }


    /**
     * 获取优先级
     * */
    public int getPriority() { return priority; }

    /**
     * 设置优先级
     * */
    public void setPriority(int priority) {

        //目前仅有三种状态，init，user，system，暂时用不到这个接口
        //this.priority = priority;
    }

    /**
     * 执行代码段
     * */
    public void run() {
        myRunnable.run();
    }

}
